EP5. 최신 LLM 구조 2편 — 위치 임베딩의 발전 (RoPE · ALiBi · NTK-Aware · LongRoPE · YaRN)
기존 절대 위치 임베딩의 외삽 실패·상대 거리 비효율 문제를 해결하기 위해 RoPE(벡터 회전)·ALiBi(선형 패널티)·NTK-Aware(동적 스케일링)·LongRoPE(선택적 스케일링)·YaRN(어텐션 온도 보정)이 순차적으로 발전하였으며, 이 위치 인코딩 기법의 선택이 현대 LLM의 긴 컨텍스트 처리 성능을 결정하는 핵심 요인이다.
1. 주제 정의
위치 임베딩(Positional Embedding)은 트랜스포머 모델이 시퀀스 내 각 토큰의 위치 정보를 인식할 수 있도록 임베딩 벡터에 위치 신호를 부여하는 기법이다. 트랜스포머의 Self-Attention은 구조적으로 위치 불변(position-invariant)이므로, 별도 위치 신호 없이는 "고양이가 쥐를 쫓았다"와 "쥐가 고양이를 쫓았다"를 구별하지 못한다.
본 에피소드에서 다루는 기법들은 모두 추론 시 컨텍스트 길이 확장과 상대 위치 인식 정확도 향상을 목표로 한다:
| 기법 | 분류 | 핵심 아이디어 |
|---|---|---|
| 기존 Sinusoidal / Learned | 절대 위치 | 값을 더함 |
| RoPE | 상대 위치 (회전) | 벡터를 회전 |
| ALiBi | 어텐션 바이어스 | 거리 선형 패널티 |
| NTK-Aware | 동적 스케일링 | 컨텍스트 길이에 따라 회전율 조절 |
| LongRoPE | 선택적 스케일링 | 고주파·저주파 차원 분리 스케일링 |
| YaRN | 안정화 보정 | Attention Temperature로 어텐션 스코어 정규화 |
2. 풀려는 문제
기존 절대 위치 임베딩(학습형 또는 Sinusoidal)은 두 가지 근본적 한계를 가진다.
문제 1 — 외삽 성능 저하 (Extrapolation Degradation)
훈련 데이터에서 최대 N 토큰 위치까지만 학습했을 때, N+1 이상의 위치는 학습된 적이 없으므로 OOD(Out-Of-Distribution) 상태가 된다. 예를 들어, 100 토큰까지 훈련했으나 150번째 토큰이 입력되면 해당 위치 표현 능력이 급격히 저하된다.
문제 2 — 상대 거리 학습 비효율
절대 위치만 학습했기 때문에, 위치 3→5(2 간격)와 위치 8→10(2 간격)이 의미적으로 동일한 거리임을 모델이 직접 학습하지 못한다. 이를 간접 학습으로만 해결해야 하므로 비효율적이다.
이 두 문제로 인해 긴 컨텍스트 처리 실패·상대 위치 인식 부족이 발생하며, 현대 LLM 평가에서 긴 컨텍스트 처리 능력이 핵심 벤치마크인 만큼 위치 인코딩 기법은 모델 학습 데이터보다 더 중요한 성능 결정 요소로 부각된다.
3. 핵심 개념·구조
3.1 RoPE (Rotary Positional Embedding)
기존 방식이 임베딩 벡터에 위치 값을 더하는 방식이라면, RoPE는 벡터를 위치에 비례한 각도만큼 회전시킨다.
- 핵심 원리: 토큰 임베딩의 차원을 2개씩 쌍으로 묶어, 위치
m에 따라 라디안 값θ만큼 회전 적용 - 상대 위치 의존: 어텐션 내적 계산 시 두 토큰의 유사도가 절대 위치가 아닌 상대적 거리에 의존하도록 수식이 설계됨
- 길이 보존: 벡터 회전은 벡터의 크기(norm)를 변경하지 않으므로 의미 정보 손실 없음 (지름 1 cm 선분을 회전해도 길이는 1 cm)
- 한계: 학습된 최대 길이를 초과하면 여전히 OOD 발생
transformers 구현: modeling_llama.py에서 LlamaRotaryEmbedding 클래스 참조
# transformers LlamaRotaryEmbedding 핵심 패턴 (간략화)
cos = emb.cos()[position_ids] # [batch, seq_len, head_dim]
sin = emb.sin()[position_ids]
q, k = apply_rotary_pos_emb(q, k, cos, sin)
3.2 ALiBi (Attention with Linear Biases)
RoPE의 OOD 한계를 보강하기 위해 어텐션 점수 계산 시 거리에 비례한 선형 패널티를 적용한다.
- 메커니즘:
Attention Score = QK^T / √d - m * |i - j|(m: 헤드별 기울기 상수, i-j: 토큰 간 거리) - 지역성 편향(Locality Bias) 강화: 거리가 멀수록 어텐션 가중치가 감소
- 학습 파라미터 불필요: 선형 함수이므로 훈련 없이 고속 작동
- 고정 컨텍스트 의존: 특정 길이에 최적화된 기울기를 사용하므로, 가변 길이 입력에 비효율적
- 현재 상태: 강의(00:04:19)에서 명시적으로 "지금은 잘 사용되지 않는다"고 언급
💡 실무 노하우 — ALiBi는 고정 컨텍스트 길이 애플리케이션(예: 항상 3,000자 이내 질의)에서는 성능이 안정적이지만, 컨텍스트 길이가 가변적인 프로덕션 환경에서는 RoPE 계열 기법이 더 적합하다.
3.3 NTK-Aware Scaling (동적 스케일링)
RoPE에서 컨텍스트가 길어지면 회전 각도가 겹쳐 위치 구분이 불가능해지는 문제를 회전율을 동적으로 조정하여 해결한다.
- 원리: 컨텍스트 길이 L에 맞게 회전 각도를
360° / L수준으로 스케일링 → 절대 겹치지 않음 - 구현:
rope_scaling={"type": "dynamic", "factor": 2.0}(vLLM·transformers 공통 설정) - 한계: 토큰 수가 매우 많을 때 회전 각도가 극히 작아져 위치 인코딩 변화량이 미미해짐
vLLM 설정 예시:
# vLLM RoPE dynamic scaling (https://github.com/vllm-project/vllm)
rope_scaling = {"type": "dynamic", "factor": 4.0}
⚠️ 주의 —
factor값이 클수록 컨텍스트 확장 범위는 넓어지지만, 짧은 컨텍스트에서 품질 저하가 발생할 수 있다. 운영 환경의 실제 컨텍스트 분포를 기준으로 factor를 설정한다.
3.4 LongRoPE (선택적 스케일링)
NTK-Aware의 일괄 스케일링 부작용(긴 토큰에서 위치 인코딩 변화량 극소화)을 해결한다. 차원의 주파수에 따라 스케일링 전략을 분리한다.
- 고주파 차원(앞쪽 차원): 단거리 토큰용 → 스케일링 없이 원래 큰 각도 유지 (예: 최소 3°)
- 저주파 차원(뒤쪽 차원): 장거리 토큰용 → 스케일링 적용으로 작은 각도 부여 (예: 0.1°~0.3°)
- 효과: 짧은 거리 토큰은 큰 의미 차이, 긴 거리 토큰은 겹치지 않는 고유 위치 보장
transformers Mistral 구현 참조: modeling_mistral.py
# rope_scaling type=longrope (transformers)
rope_scaling = {"type": "longrope", "long_factor": [...], "short_factor": [...]}
3.5 YaRN (Yet another RoPE extensioN with normalization)
RoPE 계열 모든 스케일링 기법 적용 후 발생하는 임베딩 불일치(Embedding Mismatch)를 Attention Temperature 보정으로 안정화한다.
- 임베딩 불일치: 위치 스케일링으로 임베딩 값이 크게 변하면 어텐션 스코어가 훈련 분포 밖으로 이탈
- 보정 방식: 미리 계산된 보정 계수로 어텐션 스코어를 재정규화
- 범용성: 일반 RoPE, NTK-Aware, LongRoPE 어디에도 적용 가능 — YaRN은 "어떤 RoPE를 쓰느냐"가 아니라 "보정값 적용 유무"로 정의됨
vLLM 설정:
rope_scaling = {"type": "yarn", "factor": 4.0, "original_max_position_embeddings": 4096}
💡 실무 노하우 — YaRN은 독립 기법이 아니라 보정 레이어로 이해해야 한다. 기존 RoPE/NTK/LongRoPE 모델에 사후 적용이 가능하므로, 파인튜닝 없이 컨텍스트 확장이 필요할 때 가장 먼저 검토한다.
4. 구현 가이드 (Do It Yourself)
시작 전 (Before you begin)
다음 환경을 준비합니다.
Python 3.10+
torch >= 2.0
transformers >= 4.36.0 # LongRoPE 지원
vllm >= 0.3.0 # YaRN rope_scaling 지원
📚 참고 — Hugging Face transformers 설치:
pip install transformers>=4.36.0vLLM 설치:pip install vllm(CUDA 12.1+ 권장)
Step 1 — RoPE 기반 모델 로드 및 기본 추론
- transformers로 LLaMA 계열 모델을 로드합니다. LLaMA 3.1/3.2는 기본적으로 RoPE를 사용합니다.
from transformers import AutoTokenizer, AutoModelForCausalLM
model_id = "meta-llama/Llama-3.1-8B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype="auto")
- 모델 설정에서
rope_scaling필드를 확인합니다.
print(model.config.rope_scaling) # None 이면 기본 RoPE
✅ 확인 —
model.config.rope_scaling가 출력되고 모델이 정상 로드되면 Step 1 완료.
Step 2 — NTK-Aware Dynamic Scaling 적용
- transformers의
config.json에서rope_scaling파라미터를 설정합니다.
from transformers import AutoConfig
config = AutoConfig.from_pretrained(model_id)
config.rope_scaling = {"type": "dynamic", "factor": 4.0}
model = AutoModelForCausalLM.from_pretrained(model_id, config=config)
- 확장된 컨텍스트로 추론합니다 (기본 4096 → 16384).
inputs = tokenizer(long_text, return_tensors="pt", max_length=16384)
outputs = model.generate(**inputs, max_new_tokens=256)
⚠️ 주의 — dynamic scaling은 추론 시 실제 입력 길이에 따라 계산 비용이 증가한다. 배치 추론 시 패딩으로 인한 불필요한 비용을 피하기 위해
padding_side="left"+attention_mask활용을 권장한다.✅ 확인 — 16K 토큰 이상 입력 시 OOM 없이 출력이 생성되면 Step 2 완료.
Step 3 — YaRN 적용으로 품질 안정화
- vLLM을 사용해 YaRN 스케일링을 활성화합니다.
from vllm import LLM, SamplingParams
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
rope_scaling={"type": "yarn", "factor": 4.0,
"original_max_position_embeddings": 8192},
max_model_len=32768,
)
- text-generation-inference(TGI)에서 동일하게 적용합니다.
# https://github.com/huggingface/text-generation-inference
docker run --gpus all -p 8080:80 \
-e ROPE_SCALING='{"type":"yarn","factor":4.0}' \
ghcr.io/huggingface/text-generation-inference:latest \
--model-id meta-llama/Llama-3.1-8B-Instruct
💡 실무 노하우 — YaRN은 factor 2~4 범위에서 품질 저하 없이 컨텍스트를 확장하는 것으로 실증됐다. factor > 8 은 perplexity 증가가 관찰되므로 프로덕션에서는 4 이하를 권장한다.
✅ 확인 — YaRN 적용 모델이 32K 토큰 입력에서 coherent한 출력을 생성하고 어텐션 점수가 nan/inf 없이 정상 분포하면 Step 3 완료.
Step 마지막 — 동작 확인 (테스트)
컨텍스트 확장 품질을 검증합니다.
# 니들-인-헤이스택 (Needle-in-a-Haystack) 패턴으로 검증
needle = "비밀 코드는 XK-7742 입니다."
haystack = "관련 없는 텍스트 ... " * 500 # ~16K 토큰
prompt = haystack[:8000] + needle + haystack[8000:] + "\n비밀 코드는?"
result = model.generate(tokenizer(prompt, return_tensors="pt").input_ids)
assert "XK-7742" in tokenizer.decode(result[0])
✅ 확인 — 긴 컨텍스트 중간에 삽입된 정보를 모델이 정확히 회수하면 최종 검증 완료.
5. 적용 사례 (공신력 오픈소스 5가지+)
1. Hugging Face transformers — LLaMA·Mistral RoPE 구현
transformers는 RoPE, dynamic scaling, YaRN을 공식 지원하며, rope_scaling config 파라미터로 기법을 선택한다.
modeling_llama.py—LlamaRotaryEmbedding,LlamaDynamicNTKScalingRotaryEmbeddingmodeling_mistral.py— Sliding Window Attention + RoPE 조합
2. vLLM — RoPE Scaling 프로덕션 서빙
vllm-project/vllm은 rope_scaling 파라미터로 linear, dynamic, yarn 타입을 지원한다. PagedAttention과 결합해 긴 컨텍스트 배치 추론을 효율적으로 처리한다.
3. text-generation-inference (TGI)
huggingface/text-generation-inference는 Docker 환경에서 RoPE scaling을 환경 변수로 설정할 수 있으며, 고성능 프로덕션 LLM 서빙에 사용된다.
4. llama.cpp — 로컬 RoPE·YaRN 추론
ggerganov/llama.cpp는 --rope-scaling 및 --yarn-ext-factor 플래그로 YaRN을 활성화하며, GGUF 양자화 모델에서도 긴 컨텍스트 추론을 지원한다.
# llama.cpp YaRN 추론
./llama-cli -m model.gguf --rope-scaling yarn --yarn-ext-factor 1.0 -c 32768
5. exllamav2 — NTK-Aware RoPE 양자화 추론
turboderp/exllamav2는 NTK-Aware RoPE를 INT4 양자화와 결합하여 소비자 GPU에서도 32K+ 컨텍스트 추론을 가능하게 한다.
6. ollama — Llama·Mistral 로컬 실행
ollama/ollama는 Llama·Mistral 모델의 RoPE scaling을 자동으로 처리하며, OLLAMA_NUM_CTX 환경 변수로 컨텍스트 길이를 조정한다.
OLLAMA_NUM_CTX=16384 ollama run llama3.1
7. Anthropic Python SDK — 긴 컨텍스트 API 활용
anthropics/anthropic-sdk-python을 사용해 Claude의 긴 컨텍스트 처리를 활용한다.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": long_document_prompt}],
)
⚠️ 주의 — Claude API의 긴 컨텍스트 요청은 입력 토큰 비용이 선형으로 증가한다. Prompt Caching (
cache_control) 활성화로 반복 컨텍스트 비용을 최대 90% 절감할 수 있다.
6. 핵심 원리
원리 1 — 회전 불변성 (Rotation Invariance)
RoPE의 핵심은 두 토큰 m, n의 내적이 절대 위치 m, n이 아닌 상대 거리 m-n에만 의존하도록 설계된다는 점이다. 이는 회전 행렬의 수학적 성질에서 도출된다:
<f(q, m), f(k, n)> = g(q, k, m-n)
이 성질이 성립하는 유일한 해가 회전 변환이며, 이것이 RoPE의 이름의 근거다.
원리 2 — 선형 패널티의 고정성
ALiBi의 선형 패널티 m * |i-j|는 학습되지 않는 고정값이다. 이 설계는 외삽 범위에서도 일관된 패널티 적용을 보장하지만, 동시에 컨텍스트 길이에 따른 적응력을 포기한다.
원리 3 — 주파수 도메인 분리 (LongRoPE)
임베딩 차원을 주파수 관점에서 보면, 앞쪽 차원(고주파)은 단거리 위치 차이에 민감하고 뒤쪽 차원(저주파)은 장거리 위치에 반응한다. LongRoPE는 이 주파수 특성을 활용해 차원별 차등 스케일링을 적용한다.
원리 4 — 어텐션 온도 정규화
어텐션 스코어 softmax(QK^T / √d)에서 Q, K 벡터의 크기가 커지면 softmax 입력이 샤프해져 특정 토큰에 집중도가 과도하게 높아진다. YaRN은 스케일 팩터를 조정해 이를 훈련 분포 범위로 복원한다.
7. 변형·확장
LLaMA 3.1의 RoPE 확장
Meta는 LLaMA 3.1에서 기존 8K 컨텍스트를 128K로 확장할 때 YaRN 기반 보정을 적용했다. config.json에 rope_scaling 필드가 명시돼 있다.
Mistral의 Sliding Window Attention + RoPE
Mistral은 RoPE와 함께 Sliding Window Attention을 결합해 긴 컨텍스트를 처리하며, 창(window) 밖 토큰은 어텐션 대상에서 제외한다.
Gemma2의 Logit Soft-Capping
Google Gemma2는 어텐션 로짓에 soft-cap을 적용해 YaRN과 유사한 안정화 효과를 얻는다.
Code LLaMA의 Long Context Fine-tuning
Code LLaMA는 RoPE dynamic scaling으로 컨텍스트를 100K까지 확장했으며, 장문 코드 파일 처리에 특화됐다.
8. 다른 도구·접근과의 비교 (3-way)
| 항목 | RoPE + NTK/YaRN | ALiBi | Absolute Positional |
|---|---|---|---|
| 외삽 성능 | 우수 (동적 스케일링) | 보통 (선형 패널티) | 불가 |
| 상대 위치 인식 | 네이티브 지원 | 간접적 (locality bias) | 미지원 |
| 학습 파라미터 | 없음 | 없음 | 있음 (Learned PE) |
| 컨텍스트 유연성 | 높음 | 낮음 (고정 최적화) | 낮음 |
| 추론 속도 | 중간 | 빠름 | 빠름 |
| 현재 채택률 | 지배적 | 감소 중 | 거의 없음 |
| 대표 모델 | LLaMA 3, Mistral, Gemma | BLOOM (초기) | GPT-2 |
💡 실무 노하우 — 신규 모델 선택 시
config.json의rope_scaling.type을 확인한다.yarn또는longrope가 명시된 모델은 긴 컨텍스트 최적화가 이미 적용된 것이므로 추가 설정 없이 활용 가능하다.
9. 한계·트레이드오프
RoPE 계열 공통 한계
- 파인튜닝 없는 스케일링 품질 한계: 스케일링 factor가 클수록 훈련 분포 이탈 가능성 증가
- Lost in the Middle 현상: 컨텍스트가 길어질수록 중간 부분 정보를 모델이 간과하는 현상 — 위치 인코딩만으로 완전히 해결되지 않음
ALiBi 한계
- 고정 선형 함수로 인해 컨텍스트 길이 다양성에 취약
- 주요 모델에서 사용 감소 추세 (강의 원문: "알리비는 좋았지만 지금은 안 쓴다")
NTK-Aware 한계
- 매우 긴 입력에서 회전 각도가 극소화 → 위치 구분력 저하
- 이 부작용이 LongRoPE 개발의 직접적 동기
YaRN 한계
- 보정 계수가 특정 베이스 모델·훈련 분포에 맞춰 사전 계산됨 → 타 모델에 직접 이전 불가
- 보정 계수 재계산을 위해 소규모 파인튜닝이 필요한 경우 있음
⚠️ 주의 — 컨텍스트 확장 기법은 "위치 인코딩 관점"의 해결책이다. 어텐션의 계산 복잡도 O(n²)·메모리 O(n²) 문제는 별도로 FlashAttention·Sliding Window Attention 등의 어텐션 효율화 기법이 필요하다.
10. 최신 권장 패턴
패턴 1 — 모델 선택 시 체크리스트
✓ config.json의 rope_scaling.type 확인
✓ 훈련 max_position_embeddings 확인
✓ 목표 컨텍스트 / 훈련 컨텍스트 비율(factor) 계산
✓ factor <= 4 이면 YaRN 직접 적용 가능
✓ factor > 4 이면 파인튜닝 포함 LongRoPE 권장
패턴 2 — vLLM + YaRN 프로덕션 설정 (권장)
# https://github.com/vllm-project/vllm — 프로덕션 권장 설정
from vllm import LLM
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
rope_scaling={"type": "yarn", "factor": 2.0,
"original_max_position_embeddings": 8192},
max_model_len=16384,
)
패턴 3 — Anthropic SDK 긴 컨텍스트 + Prompt Caching
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
system=[{"type": "text", "text": system_prompt,
"cache_control": {"type": "ephemeral"}}],
messages=[{"role": "user", "content": long_context_query}],
)
📚 참고 — Anthropic SDK Prompt Caching 공식 문서: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
패턴 4 — 로컬 추론 (llama.cpp + YaRN)
# https://github.com/ggerganov/llama.cpp
./llama-cli -m llama-3.1-8b.Q4_K_M.gguf \
--rope-scaling yarn --yarn-ext-factor 1.0 \
-c 32768 --threads 8
💡 실무 노하우 — 긴 컨텍스트 처리 표준 스택은 RoPE + YaRN (보정) + FlashAttention (효율화) 조합이다. 모델 아키텍처 문서에서
rope_type,attention_bias,sliding_window세 필드를 먼저 확인하면 위치 인코딩 전략을 빠르게 파악할 수 있다.
11. 메타인지 자기평가
이 섹션의 질문에 답변 가능 여부를 스스로 점검합니다.
| 질문 | 핵심 개념 |
|---|---|
| RoPE가 상대 위치에 의존하는 이유를 수식 수준에서 설명할 수 있는가? | 회전 행렬의 내적 성질 |
| ALiBi가 현재 잘 사용되지 않는 이유를 2가지 이상 설명할 수 있는가? | 고정 선형 함수 한계, 가변 길이 비효율 |
| NTK-Aware와 LongRoPE의 차이를 1문장으로 설명할 수 있는가? | 일괄 vs 선택적 스케일링 |
| YaRN을 기존 RoPE 모델에 적용하는 방법을 구체적으로 설명할 수 있는가? | rope_scaling config, 파인튜닝 유무 |
| 프로덕션에서 factor 값을 결정하는 기준을 말할 수 있는가? | 운영 컨텍스트 분포, factor <= 4 |
심화 학습 경로: 1. Hugging Face Course — Transformers 내부 구조 2. OpenAI Cookbook — 긴 컨텍스트 처리 패턴 3. Anthropic Quickstart — Claude 긴 컨텍스트 API 4. RoPE 원 논문: Su et al. (2021) "RoFormer: Enhanced Transformer with Rotary Position Embedding" 5. YaRN 원 논문: Peng et al. (2023) "YaRN: Efficient Context Window Extension of Large Language Models"
클릭하거나 Space를 눌러 뒤집기